5.6 GPU

要点
一些免费的 gpu

查看是否安装 GPU 和 CUDA:

!nvidia-smi
Wed Sep 20 08:41:47 2023       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 470.103.01   Driver Version: 470.103.01   CUDA Version: 11.4     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  Tesla T4            On   | 00000000:00:07.0 Off |                    0 |
| N/A   42C    P0    27W /  70W |    506MiB / 15109MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
+-----------------------------------------------------------------------------+

可以看到有一块 GPU, 型号是 Tesla T4,内存是 16G

1. 计算设备

默认情况下,张量是在内存中创建的,然后使用 CPU 计算它。

# 查询 GPU 个数
torch.cuda.device_count() # 1

可以取 GPU、CPU 地址存储为 torch.device 对象,方便后续张量、网络指定存储地址(默认是 CPU ), 注意 cuda:0cuda 是等价的

device = torch.device('cuda:0') 
注意

这个操作本身并不会触发任何与硬件交互的操作。换句话说,这只是创建了一个指向特定 CUDA 设备的标识符,但并没有实际去检查该设备是否存在。

device = torch.device('cuda:10') # 这行代码不会报错 
x = torch.tensor([1.0, 2.0])  
x = x.to(device)  # 这行代码会报错,因为系统上没有名为'cuda:10'的设备

2. 张量与 GPU

# 查询张量所在设备
x = torch.tensor([1, 2, 3])
x.device
device(type='cpu') # 默认在CPU

无论何时我们要对多个项进行操作,它们都必须在同一个设备上。例如,如果我们对两个张量求和,我们需要确保两个张量都位于同一个 device 上,否则框架将不知道在哪里存储结果,甚至不知道在哪里执行计算。

X = torch.ones(2, 3, device=torch.device('cuda'))
Y = torch.rand(2, 3, device=torch.device('cpu'))

X + Y # 会报错,原因不在一个 device 上

利用 .cuda() 方法在另一个 GPU 创建同样的张量

Z = Y.cuda(0) # 在第 0 块 GPU 上创建同样的 Y
X + Z # 可以运算

Z.cuda(0) is Z # True  在本身 device 上不会创建副本,而是直接返回本身(性能考虑)

Pytorch 不允许不在同一 device 的张量做运算,因为对于数据在 cpu 和 gpu 之间迁移非常耗时,如果有一层在 cpu,其他都在 gpu,学习过程中数据得来回搬迁,非常耗时

注意

与下一小节的 net.to(device)不同,net.to(device) 直接就把网络的参数搬到 device 上了, X.to(device) 实际上是返回一个新对象,一般用 X = X.to(device)X 搬到新设备上

3. 神经网络与 GPU

神经网络所在的设备指的是网络的参数所在的设备

net = nn.Sequential(nn.Linear(3, 1))
net = net.to(device=torch.device('cuda:0')) # .to 方法移到 cuda0 上

不像张量有 .device 方法,这些子模块或参数有可能分布在不同的设备上(虽然这种情况并不常见),要查看模型所在设备,可以用:next(model.parameters()).device,执行这段代码总是返回网络第一层 weight 所在的设备

参考文献



© 2023 yanghn. All rights reserved. Powered by Obsidian